package cn.chenfeifx.core.controls;

import javafx.beans.property.DoubleProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.geometry.Insets;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Region;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Polygon;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;

/**
 * 弹出窗口
 */
public class PopoverNode extends Region {

    private static final double size = 6;
    // 三角形
    private final Polygon triangle;
    // 矩形
    private final Rectangle rectangle;
    //
    private final Region content;

    public PopoverNode(Region content) {
        this.content = content;
        triangle = new Polygon();
        rectangle = new Rectangle();
        initialize();
    }

    private void initialize() {
        content.setMaxSize(USE_PREF_SIZE, USE_PREF_SIZE);
        content.setPadding(new Insets(3, 0, 3, 0));
        getChildren().setAll(new Pane(), content);
        rectangle.setArcHeight(6);
        rectangle.setArcWidth(6);
        rectangle.widthProperty().bind(content.widthProperty());
        rectangle.heightProperty().bind(content.heightProperty());
        // 布局监听
        content.layoutBoundsProperty().addListener((observable, oldValue, newValue) -> resetLayout());
        trianglePos.addListener((observable, oldValue, newValue) -> resetLayout());
        offset.addListener((observable, oldValue, newValue) -> resetLayout());
    }

    public void setContent(Region content) {
        getChildren().set(1, content);
        content.layoutBoundsProperty().addListener((observable, oldValue, newValue) -> resetLayout());
    }

    public Region getContent() {
        return content;
    }

    /**
     * 重新布局样式
     */
    public void resetLayout() {
        double width = content.getWidth();
        double height = content.getHeight();
        switch (getTrianglePos()) {
            case TOP -> {
                triangle.getPoints().setAll(size, 0D, 0D, size, size * 2, size);
                triangle.setLayoutY(-size);
                triangle.setLayoutX((getOffset() < 0 ? width / 2 : getOffset()) - size);
            }
            case RIGHT -> {
                triangle.getPoints().setAll(0D, 0D, size, size, 0D, size * 2);
                triangle.setLayoutX(width);
                triangle.setLayoutY((getOffset() < 0 ? height / 2 : getOffset()) - size);
            }
            case LEFT -> {
                triangle.getPoints().setAll(0D, size, size, 0D, size, size * 2);
                triangle.setLayoutX(-size);
                triangle.setLayoutY((getOffset() < 0 ? height / 2 : getOffset()) - size);
            }
            case BOTTOM -> {
                triangle.getPoints().setAll(0D, 0D, size * 2, 0D, size, size);
                triangle.setLayoutY(rectangle.getHeight());
                triangle.setLayoutX((getOffset() < 0 ? width / 2 : getOffset()) - size);
            }
        }
        Shape union = Shape.union(triangle, rectangle);
        union.setFill(getFill());
        union.setStroke(getStroke());
        union.setStrokeWidth(0.5);
        getChildren().set(0, union);
    }

    // 三角形位置
    private final ObjectProperty<Pos> trianglePos = new SimpleObjectProperty<>(Pos.TOP);

    public Pos getTrianglePos() {
        return trianglePos.get();
    }

    public ObjectProperty<Pos> trianglePosProperty() {
        return trianglePos;
    }

    public void setTrianglePos(Pos trianglePos) {
        this.trianglePos.set(trianglePos);
    }

    // offset 偏离量
    private final DoubleProperty offset = new SimpleDoubleProperty(-1);

    public double getOffset() {
        return offset.get();
    }

    public DoubleProperty offsetProperty() {
        return offset;
    }

    public void setOffset(double offset) {
        this.offset.set(offset);
    }

    // fill color
    private final ObjectProperty<Paint> fill = new SimpleObjectProperty<>(Color.WHITE);

    public Paint getFill() {
        return fill.get();
    }

    public ObjectProperty<Paint> fillProperty() {
        return fill;
    }

    public void setFill(Paint fill) {
        this.fill.set(fill);
    }

    // stroke color
    private final ObjectProperty<Paint> stroke = new SimpleObjectProperty<>(Color.valueOf("#CDD0D6"));

    public Paint getStroke() {
        return stroke.get();
    }

    public ObjectProperty<Paint> strokeProperty() {
        return stroke;
    }

    public void setStroke(Paint stroke) {
        this.stroke.set(stroke);
    }

    /**
     * 三角形位置 上，右，左，下
     */
    public enum Pos {
        TOP, RIGHT, LEFT, BOTTOM
    }

}
